package com.mdd.admin.service.refund.impl;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.bean.request.WxPayRefundV3Request;
import com.github.binarywang.wxpay.bean.result.WxPayRefundQueryV3Result;
import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.google.common.collect.Lists;
import com.mdd.admin.service.log.IOrderRefundLogService;
import com.mdd.admin.service.pay.ICBCService;
import com.mdd.admin.service.refund.IOrderRefundService;
import com.mdd.admin.validate.refund.OrderRefundPageParam;
import com.mdd.admin.vo.refund.OrderRefundDetailVo;
import com.mdd.admin.vo.refund.OrderRefundListVo;
import com.mdd.admin.vo.refund.StatisticsOrderRefundCountVo;
import com.mdd.admin.vo.refund.StatisticsOrderRefundVo;
import com.mdd.common.config.AlipayConfig;
import com.mdd.common.core.PageResult;
import com.mdd.common.dto.OrderRefundDto;
import com.mdd.common.dto.result.OrderRefundPageResultDto;
import com.mdd.common.entity.account.AccountLog;
import com.mdd.common.entity.log.OrderRefundLog;
import com.mdd.common.entity.order.Order;
import com.mdd.common.entity.refund.OrderRefund;
import com.mdd.common.entity.user.User;
import com.mdd.common.enums.*;
import com.mdd.common.exception.OperateException;
import com.mdd.common.mapper.account.AccountLogMapper;
import com.mdd.common.mapper.log.OrderRefundLogMapper;
import com.mdd.common.mapper.order.OrderMapper;
import com.mdd.common.mapper.refund.OrderRefundMapper;
import com.mdd.common.mapper.user.UserMapper;
import com.mdd.common.plugin.notice.NoticeDriver;
import com.mdd.common.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * 订单退款实现类
 */
@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class OrderRefundServiceImpl extends ServiceImpl<OrderRefundMapper, OrderRefund> implements IOrderRefundService {

    @Resource
    OrderRefundMapper orderRefundMapper;
    @Resource
    private AccountLogMapper accountLogMapper;

    @Resource
    private IOrderRefundLogService orderRefundLogService;
    @Resource
    private OrderRefundLogMapper orderRefundLogMapper;
    @Resource
    private UserMapper userMapper;

    @Resource
    private OrderMapper orderMapper;

    @Resource
    private ICBCService icbcService;

    /**
     * 订单退款列表
     *
     * @param params 搜索参数
     * @return PageResult<OrderRefundListVo>
     * @author slien
     */
    @Override
    public PageResult<OrderRefundListVo> list(OrderRefundPageParam params) {
        Page<OrderRefundPageResultDto> page = new Page<>(params.getPageNo(), params.getPageSize());
        OrderRefundDto pageDto = new OrderRefundDto();
        BeanUtils.copyProperties(params, pageDto);
        pageDto.setOrderTimeStart(TimeUtil.dateToTimestamp(params.getOrderTimeStart()));
        pageDto.setOrderTimeEnd(TimeUtil.dateToTimestamp(params.getOrderTimeEnd()));
        Page<OrderRefundPageResultDto> resultDtoPage = orderRefundMapper.page(page, pageDto);
        if (resultDtoPage == null || CollectionUtils.isEmpty(resultDtoPage.getRecords())) {
            return PageResult.iPageHandle(page.getTotal(), page.getCurrent(), page.getSize(), Lists.newArrayList());
        }

        Map<Integer, String> refundStatusMap = OrderRefundStatusEnum.getMap();
        Map<Integer, String> operateMap = RefundOperateEnum.getMap();
        Map<Integer, String> clientMap = ClientEnum.getMap();
        List<OrderRefundListVo> list = new LinkedList<>();
        for (OrderRefundPageResultDto item : resultDtoPage.getRecords()) {
            OrderRefundListVo vo = new OrderRefundListVo();
            BeanUtils.copyProperties(item, vo);
            vo.setCreateTime(TimeUtil.timestampToDate(item.getCreateTime()));
            vo.setUpdateTime(TimeUtil.timestampToDate(item.getUpdateTime()));
            vo.setRefundTime(TimeUtil.timestampToDate(item.getRefundTime()));
            vo.setAvatar(UrlUtil.toAbsoluteUrl(item.getAvatar()));
            vo.setRefundStatusName(refundStatusMap.get(vo.getRefundStatus()));
            vo.setTypeName(operateMap.get(vo.getType()));
            vo.setOrderTerminalName(clientMap.get(vo.getOrderTerminal()));
            vo.setRemark(item.getRemark());
            vo.setReviewStatus(item.getReviewStatus());
            list.add(vo);
        }

        return PageResult.iPageHandle(resultDtoPage.getTotal(), resultDtoPage.getCurrent(), resultDtoPage.getSize(), list);
    }

    @Override
    public StatisticsOrderRefundVo statisticsAmount() {
        List<OrderRefund> list = super.list();
        if (CollectionUtils.isEmpty(list)) {
            return new StatisticsOrderRefundVo();
        }
        StatisticsOrderRefundVo refundVo = new StatisticsOrderRefundVo();
        BigDecimal totalAmount = BigDecimal.ZERO;
        BigDecimal refundingAmount = BigDecimal.ZERO;
        BigDecimal refundAmount = BigDecimal.ZERO;
        BigDecimal failRefundAmount = BigDecimal.ZERO;
        for (OrderRefund orderRefund : list) {
            if (OrderRefundStatusEnum.REFUNDING.getStatus() == orderRefund.getRefundStatus()) {
                refundingAmount = refundingAmount.add(orderRefund.getRefundAmount());
            } else if (OrderRefundStatusEnum.SUCCESS.getStatus() == orderRefund.getRefundStatus()) {
                refundAmount = refundAmount.add(orderRefund.getRefundAmount());
            } else {
                failRefundAmount = failRefundAmount.add(orderRefund.getRefundAmount());
            }
            totalAmount = totalAmount.add(orderRefund.getRefundAmount());
        }
        refundVo.setRefundTotalAmount(totalAmount);
        refundVo.setRefundingAmount(refundingAmount);
        refundVo.setRefundAmount(refundAmount);
        refundVo.setFailRefundAmount(failRefundAmount);
        return refundVo;
    }

    @Override
    public StatisticsOrderRefundCountVo statisticsCount(OrderRefundPageParam params) {
        OrderRefundDto pageDto = new OrderRefundDto();
        BeanUtils.copyProperties(params, pageDto);
        pageDto.setOrderTimeStart(TimeUtil.dateToTimestamp(params.getOrderTimeStart()));
        pageDto.setOrderTimeEnd(TimeUtil.dateToTimestamp(params.getOrderTimeEnd()));
        List<OrderRefundPageResultDto> list = orderRefundMapper.selectListByParams(pageDto);
        if (CollectionUtils.isEmpty(list)) {
            return new StatisticsOrderRefundCountVo();
        }
        StatisticsOrderRefundCountVo refundVo = new StatisticsOrderRefundCountVo();
        long refundingCount = list.stream().map(OrderRefundPageResultDto::getRefundStatus).filter(item -> OrderRefundStatusEnum.REFUNDING.getStatus() == item).count();
        long successCount = list.stream().map(OrderRefundPageResultDto::getRefundStatus).filter(item -> OrderRefundStatusEnum.SUCCESS.getStatus() == item).count();
        long failCount = list.stream().map(OrderRefundPageResultDto::getRefundStatus).filter(item -> OrderRefundStatusEnum.FAILURE.getStatus() == item).count();
        refundVo.setTotalCount(list.size());
        refundVo.setRefundingCount((int) refundingCount);
        refundVo.setRefundCount((int) successCount);
        refundVo.setFailRefundCount((int) failCount);
        return refundVo;
    }

    /**
     * 订单退款详情
     *
     * @param id 主键参数
     * @return OrderRefund
     * @author slien
     */
    @Override
    public OrderRefundDetailVo detail(Long id) {
        OrderRefund model = orderRefundMapper.selectOne(
                new QueryWrapper<OrderRefund>()
                        .eq("id", id)
                        .last("limit 1"));

        Assert.notNull(model, "数据不存在");

        OrderRefundDetailVo vo = new OrderRefundDetailVo();
        BeanUtils.copyProperties(model, vo);
        return vo;
    }

    /**
     * 订单退款删除
     *
     * @param id 主键ID
     * @author slien
     */
    @Override
    public void del(Integer id) {
        OrderRefund model = orderRefundMapper.selectOne(
                new QueryWrapper<OrderRefund>()
                        .eq("id", id)
                        .last("limit 1"));

        Assert.notNull(model, "数据不存在!");

        orderRefundMapper.delete(new QueryWrapper<OrderRefund>().eq("id", id));
    }

    @Override
    public void repeatRefund(Long refundId) throws WxPayException {
        OrderRefund orderRefund = orderRefundMapper.selectOne(
                new QueryWrapper<OrderRefund>()
                        .eq("id", refundId)
                        .last("limit 1"));
        Assert.notNull(orderRefund, "退款订单数据不存在!");
        switch (orderRefund.getRefundWay()){
            case 1:
                String sn = orderRefund.getSn();
                Order model = orderMapper.selectById(orderRefund.getOrderId());
                WxPayRefundQueryV3Result refundQueryV3 = WxPayServiceUtils.wxPayService(model.getPayChannel()).refundQueryV3(sn);
                String status = refundQueryV3.getStatus();
                // 退款成功
                if ("SUCCESS".equalsIgnoreCase(status)) {
                    orderRefund.setRefundStatus(OrderRefundStatusEnum.SUCCESS.getStatus());
                    orderRefund.setRefundTime(TimeUtil.dateToTimestamp(TimeUtil.getStringByRFC3339(refundQueryV3.getSuccessTime())));
                    return;
                } else if ("PROCESSING".equalsIgnoreCase(status)) {
                    orderRefund.setRefundStatus(OrderRefundStatusEnum.REFUNDING.getStatus());
                    return;
                } else if ("CLOSED".equalsIgnoreCase(status)) {
                    orderRefund.setRefundStatus(OrderRefundStatusEnum.CLOSE.getStatus());
                    return;
                } else {
                    WxPayRefundV3Request request = new WxPayRefundV3Request();
                    Order order = orderMapper.selectById(orderRefund.getOrderId());
                    request.setOutTradeNo(order.getSn());
                    request.setOutRefundNo(orderRefund.getSn());
                    WxPayRefundV3Request.Amount amount = new WxPayRefundV3Request.Amount();
                    amount.setCurrency("CNY");
                    amount.setRefund(AmountUtil.yuan2Fen(orderRefund.getOrderAmount()));
                    amount.setTotal(AmountUtil.yuan2Fen(orderRefund.getOrderAmount()));
                    request.setAmount(amount);
                    WxPayRefundV3Result wxPayRefundV3Result = WxPayServiceUtils.wxPayService(order.getPayChannel()).refundV3(request);
                    log.info("退款单号:{},重新发起退款的返回结果:{}", orderRefund.getSn(), wxPayRefundV3Result.toString());
                    // 保存记录退款日志
                    OrderRefundLog refundLog = new OrderRefundLog();
                    refundLog.setSn(orderRefund.getSn());
                    refundLog.setRefundId(orderRefund.getId());
                    refundLog.setType(RefundOperateEnum.TYPE_ADMIN.getType());
                    refundLog.setOperatorId(1L);
                    refundLog.setRefundAmount(orderRefund.getRefundAmount());
                    refundLog.setRefundStatus(OrderRefundStatusEnum.REFUNDING.getStatus());
                    refundLog.setWechatRefundId(wxPayRefundV3Result.getRefundId());
                    refundLog.setRefundMsg(wxPayRefundV3Result.toString());
                    refundLog.setCreateTime(TimeUtil.timestamp());
                    refundLog.setUpdateTime(TimeUtil.timestamp());
                    orderRefundLogService.saveEntity(refundLog);
                }
                break;
            case 2:
                balanceRefund(orderRefund);
                break;
        }
    }

    @Override
    public boolean updateOrderStatusToPaid(WxPayRefundNotifyResult.ReqInfo reqInfo) {
        String status = reqInfo.getRefundStatus();
        String outTradeNo = reqInfo.getOutTradeNo();

        OrderRefund orderRefund = orderRefundMapper.selectOne(
                new QueryWrapper<OrderRefund>()
                        .eq("sn", outTradeNo)
                        .last("limit 1"));
        Assert.notNull(orderRefund, "退款订单数据不存在!");
        if (OrderRefundStatusEnum.SUCCESS.getStatus() == orderRefund.getRefundStatus()) {
            return true;
        }

        // 当前状态
        Integer refundStatus = orderRefund.getRefundStatus();

        // 退款成功
        if ("SUCCESS".equalsIgnoreCase(status)) {
            orderRefund.setRefundStatus(OrderRefundStatusEnum.SUCCESS.getStatus());
            orderRefund.setRefundTime(TimeUtil.dateToTimestamp(reqInfo.getSuccessTime()));
        } else if ("PROCESSING".equalsIgnoreCase(status)) {
            orderRefund.setRefundStatus(OrderRefundStatusEnum.REFUNDING.getStatus());
        } else if ("ABNORMAL".equalsIgnoreCase(status)) {
            orderRefund.setRefundStatus(OrderRefundStatusEnum.FAILURE.getStatus());
        } else {
            orderRefund.setRefundStatus(OrderRefundStatusEnum.CLOSE.getStatus());
        }
        BigDecimal refund = FormulaUtil.divide(new BigDecimal(reqInfo.getRefundFee()), 100);
        orderRefund.setRefundAmount(refund);
        orderRefund.setTransactionId(reqInfo.getRefundId());
        //更新退款单
        orderRefundMapper.updateById(orderRefund);
        // 保存记录退款日志
        String infoRefundId = reqInfo.getRefundId();
        OrderRefundLog refundLog = orderRefundLogService.getByWechatRefundId(infoRefundId);
        if (refundLog != null) {
            refundLog.setRefundStatus(orderRefund.getRefundStatus());
            refundLog.setOperatorId(1L);
            refundLog.setRefundAmount(orderRefund.getRefundAmount());
            refundLog.setRefundMsg(reqInfo.toString());
            refundLog.setUpdateTime(TimeUtil.timestamp());
            orderRefundLogService.updateByEntityId(refundLog);
        } else {
            refundLog = new OrderRefundLog();
            refundLog.setSn(orderRefund.getSn());
            refundLog.setRefundId(orderRefund.getId());
            refundLog.setType(1);
            refundLog.setOperatorId(1L);
            refundLog.setRefundAmount(orderRefund.getRefundAmount());
            refundLog.setRefundStatus(orderRefund.getRefundStatus());
            refundLog.setWechatRefundId(reqInfo.getRefundId());
            refundLog.setRefundMsg(reqInfo.toString());
            refundLog.setCreateTime(TimeUtil.timestamp());
            refundLog.setUpdateTime(TimeUtil.timestamp());
            orderRefundLogService.saveEntity(refundLog);
        }

        // 不是退款中的就不发了
        if ("SUCCESS".equalsIgnoreCase(status) && !refundStatus.equals(OrderRefundStatusEnum.REFUNDING.getStatus())) {
            // 发送通知 (退款成功)
            try {
                Order order = orderMapper.selectById(orderRefund.getOrderId());
                Map<String, String> config = new LinkedHashMap<>();
                config.put("scene", String.valueOf(NoticeEnum.U_ORDER_REFUND.getCode()));
                config.put("mobile", order.getMobile());

                Map<String, String> params = new LinkedHashMap<>();
                params.put("user_name", order.getContact());
                params.put("order_sn", order.getSn());
                (new NoticeDriver()).handle(config, params);
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }
        return true;
    }

    @Override
    public void createAndRefund(Long orderId, Integer operateType) throws WxPayException, AlipayApiException {
        Order order = orderMapper.selectById(orderId);
        // 保存记录退款日志
        OrderRefund refund = new OrderRefund();
        refund.setSn(SnUtils.getRefundOrderSn());
        refund.setOrderId(orderId);
        refund.setUserId(order.getUserId());
        refund.setType(operateType);
        refund.setRefundWay(order.getPayWay());
        refund.setOrderTerminal(order.getOrderTerminal());
        refund.setTransactionId(null);
        refund.setOrderAmount(order.getOrderAmount());
        refund.setRefundAmount(order.getOrderAmount());
        refund.setRefundStatus(OrderRefundStatusEnum.REFUNDING.getStatus());
        refund.setCreateTime(TimeUtil.timestamp());
        refund.setTransactionId(order.getTransactionId());
        refund.setUpdateTime(TimeUtil.timestamp());
        super.save(refund);
        switch (refund.getRefundWay()){
            case 1:
//                WxPayRefundV3Request request = new WxPayRefundV3Request();
//                request.setOutTradeNo(order.getSn());
//                request.setOutRefundNo(refund.getSn());
//                WxPayRefundV3Request.Amount amount = new WxPayRefundV3Request.Amount();
//                amount.setCurrency("CNY");
//                amount.setRefund(AmountUtil.yuan2Fen(refund.getOrderAmount()));
//                amount.setTotal(AmountUtil.yuan2Fen(refund.getOrderAmount()));
//                request.setAmount(amount);
//                WxPayRefundV3Result wxPayRefundV3Result = WxPayServiceUtils.wxPayService(order.getPayChannel()).refundV3(request);
//                log.info("createAndRefund,退款返回结果:{}", wxPayRefundV3Result.toString());
//                refund.setTransactionId(wxPayRefundV3Result.getRefundId());Z
                //log.info("后台开始进行退款:  {}", order);
                icbcService.refund(refund, refund.getUserId());
                break;
            case 2:
                balanceRefund(refund);
                refund.setRefundStatus(OrderRefundStatusEnum.SUCCESS.getStatus());
                break;
            case 3:
                //AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.GATEWAY_URL, AlipayConfig.APP_ID, AlipayConfig.MERCHANT_PRIVATE_KEY, "json", AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGN_TYPE);
                AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.GATEWAY_URL, ConfigUtil.getAliDevPay("app_id"), ConfigUtil.getAliDevPay("private_key"), "json", AlipayConfig.CHARSET, ConfigUtil.getAliDevPay("ali_public_key"), AlipayConfig.SIGN_TYPE);

                AlipayTradeRefundRequest aliRequest = new AlipayTradeRefundRequest();
                AlipayTradeRefundModel alipayTradeRefundModel = new AlipayTradeRefundModel();
                alipayTradeRefundModel.setTradeNo(order.getTransactionId());
                alipayTradeRefundModel.setRefundAmount(order.getOrderAmount().toString());
                alipayTradeRefundModel.setOutRequestNo(order.getSn());
                aliRequest.setBizModel(alipayTradeRefundModel);
                AlipayTradeRefundResponse response = alipayClient.execute(aliRequest);
                if(response.isSuccess()){
                    refund.setRefundStatus(OrderRefundStatusEnum.SUCCESS.getStatus());
                    refund.setRefundWay(PaymentEnum.ALI_PAY.getCode());
                    refund.setRefundTime(TimeUtil.timestamp());
                    orderRefundMapper.updateById(refund);
                    //OrderRefund orderRefund = new OrderRefund();
                    insertBalanceOrderRefundLog(refund);
                    //System.out.println("调用支付宝退款成功");
                } else {
                    throw new OperateException("调用支付宝退款失败");
                }

        }
        super.updateById(refund);
    }

    @Override
    public List<OrderRefund> getNoRefundOrderByDuration(int minutes) {
        //minutes分钟之前的时间
        LocalDateTime localDateTime = LocalDateTime.now();
        LocalDateTime time = localDateTime.minusMinutes(minutes);
        long createTime = time.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() / 1000;
        LambdaQueryWrapper<OrderRefund> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(OrderRefund::getRefundStatus, OrderRefundStatusEnum.REFUNDING.getStatus());
        lambdaQueryWrapper.le(OrderRefund::getCreateTime, createTime);
        List<OrderRefund> refundInfoList = baseMapper.selectList(lambdaQueryWrapper);
        return refundInfoList;
    }

    @Override
    public void checkRefundStatus(String refundNo) throws Exception {
        log.warn("checkRefundStatus根据退款单号核实退款单状态 ===> {}", refundNo);
        //调用查询退款单接口
        LambdaQueryWrapper<OrderRefund> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(OrderRefund::getSn, refundNo);
        lambdaQueryWrapper.last("limit 1");
        OrderRefund model = super.getOne(lambdaQueryWrapper);
        if (OrderRefundStatusEnum.SUCCESS.getStatus() == model.getRefundStatus()) {
            return;
        }
        Order order = orderMapper.selectById(model.getOrderId());
        WxPayRefundQueryV3Result refundQueryV3 = WxPayServiceUtils.wxPayService(order.getPayChannel()).refundQueryV3(model.getSn());
        model.setRefundTime(TimeUtil.dateToTimestamp(TimeUtil.getStringByRFC3339(refundQueryV3.getSuccessTime())));
        String status = refundQueryV3.getStatus();
        if ("SUCCESS".equalsIgnoreCase(status)) {
            model.setRefundStatus(OrderRefundStatusEnum.SUCCESS.getStatus());
        } else if ("PROCESSING".equalsIgnoreCase(status)) {
            model.setRefundStatus(OrderRefundStatusEnum.REFUNDING.getStatus());
        } else if ("CLOSED".equalsIgnoreCase(status)) {
            model.setRefundStatus(OrderRefundStatusEnum.CLOSE.getStatus());
        } else {
            model.setRefundStatus(OrderRefundStatusEnum.FAILURE.getStatus());
        }
        model.setTransactionId(refundQueryV3.getTransactionId());
        Integer refund = refundQueryV3.getAmount().getRefund();
        model.setRefundAmount(AmountUtil.fen2YuanDecimal(refund));
        orderRefundMapper.updateById(model);
        // 更新退款记录
        OrderRefundLog refundLog = orderRefundLogService.getByWechatRefundId(refundQueryV3.getRefundId());
        if (refundLog == null) {
            refundLog = new OrderRefundLog();
            refundLog.setSn(model.getSn());
            refundLog.setRefundId(model.getId());
            refundLog.setType(OperateEnum.TYPE_SYSTEM.getType());
            refundLog.setOperatorId(1L);
            refundLog.setRefundAmount(model.getRefundAmount());
            refundLog.setRefundStatus(model.getRefundStatus());
            refundLog.setWechatRefundId(refundQueryV3.getRefundId());
            refundLog.setRefundMsg(refundQueryV3.toString());
            refundLog.setCreateTime(TimeUtil.timestamp());
            refundLog.setUpdateTime(TimeUtil.timestamp());
            orderRefundLogService.saveEntity(refundLog);
        } else {
            refundLog.setRefundAmount(model.getRefundAmount());
            refundLog.setRefundStatus(model.getRefundStatus());
            refundLog.setRefundMsg(refundQueryV3.toString());
            orderRefundLogService.updateByEntityId(refundLog);
        }
    }

    @Override
    public void balanceRefund(OrderRefund orderRefund) {
        try{
            if (OrderRefundStatusEnum.SUCCESS.getStatus() == orderRefund.getRefundStatus()){
                return;
            }
            Order order = orderMapper.selectOne(new QueryWrapper<Order>()
                    .eq("id", orderRefund.getOrderId())
                    .eq("is_delete", 0)
                    .last("limit 1"));
            User user = userMapper.selectOne(new QueryWrapper<User>()
                    .eq("id", order.getUserId())
                    .eq("is_delete", 0)
                    .last("limit 1"));
            user.setMoney(user.getMoney().add(orderRefund.getRefundAmount()));
            user.setUpdateTime(System.currentTimeMillis() / 1000);
            userMapper.updateById(user);
            // 插入退款日志
            insertBalanceOrderRefundLog(orderRefund);
            // 添加余额明细日志
            AccountLog accountLog = new AccountLog();
            accountLog.setUserId(order.getUserId());
            accountLog.setAssociationSn(order.getSn());
            accountLog.setAction(AccountChangeEnum.ACTION_INC.getCode());
            accountLog.setChangeType(AccountEnum.UM_INC_Wallet.getCode());
            accountLog.setLeftAmount(user.getMoney());
            accountLog.setChangeAmount(order.getOrderAmount());
            accountLog.setCreateTime(System.currentTimeMillis() / 1000);
            accountLog.setUpdateTime(System.currentTimeMillis() / 1000);
            accountLogMapper.insert(accountLog);
        }catch (Exception e){
            throw new OperateException("系统繁忙请重新操作");
        }
    }

    @Override
    public void checkBalanceRefund(OrderRefund orderRefund) {
        balanceRefund(orderRefund);
        insertBalanceOrderRefundLog(orderRefund);
    }

    @Override
    public void rebates(Long refundId,Integer reviewStatus) {
        OrderRefund orderRefund = orderRefundMapper.selectById(refundId);
        orderRefund.setReviewStatus(reviewStatus);
        orderRefundMapper.updateById(orderRefund);
        if(orderRefund.getReviewStatus().equals(OrderRefundReviewStatusEnum.SUCCESS.getStatus())){
            //调用支付接口
            icbcService.refund(orderRefund, orderRefund.getUserId());
        }
    }

    public void insertBalanceOrderRefundLog(OrderRefund orderRefund){
        OrderRefundLog orderRefundLog = new OrderRefundLog();
        orderRefundLog.setSn(orderRefund.getSn());
        orderRefundLog.setRefundId(orderRefund.getId());
        orderRefundLog.setType(OperateEnum.TYPE_SYSTEM.getType());
        orderRefundLog.setOperatorId(1L);
        orderRefundLog.setRefundAmount(orderRefund.getRefundAmount());
        orderRefundLog.setRefundStatus(OrderRefundStatusEnum.SUCCESS.getStatus());
        orderRefundLog.setWechatRefundId("");
        orderRefundLog.setRefundMsg("退款成功");
        orderRefundLog.setCreateTime(TimeUtil.timestamp());
        orderRefundLog.setUpdateTime(TimeUtil.timestamp());
        orderRefundLogService.saveEntity(orderRefundLog);
    }
}
